package org.springblade.common.config;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.util.Assert;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.CorsProcessor;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.cors.DefaultCorsProcessor;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.OncePerRequestFilter;

/**
 * 
 * @author zollty
 * @since 2022年5月26日
 */
public class MyCorsFilter extends OncePerRequestFilter {

    private final CorsConfigurationSource configSource;

    private CorsProcessor processor = new DefaultCorsProcessor();


    /**
     * Constructor accepting a {@link CorsConfigurationSource} used by the filter to find the {@link CorsConfiguration}
     * to use for each incoming request.
     * 
     * @see UrlBasedCorsConfigurationSource
     */
    public MyCorsFilter(CorsConfigurationSource configSource) {
        Assert.notNull(configSource, "CorsConfigurationSource must not be null");
        this.configSource = configSource;
    }

    /**
     * Configure a custom {@link CorsProcessor} to use to apply the matched {@link CorsConfiguration} for a request.
     * <p>
     * By default {@link DefaultCorsProcessor} is used.
     */
    public void setCorsProcessor(CorsProcessor processor) {
        Assert.notNull(processor, "CorsProcessor must not be null");
        this.processor = processor;
    }


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse res,
            FilterChain filterChain) throws ServletException, IOException {

        final HttpServletRequest httpRequest = (HttpServletRequest) request;
        String path = httpRequest.getRequestURI();

        CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request);
        boolean isValid = this.processor.processRequest(corsConfiguration, request, res);
        logger.info(path + " pass MyCorsFilter --------------------------- "
                + httpRequest.getMethod().toString() + " isValid="
                + isValid);

        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Allow-Headers", "*");

        if (CorsUtils.isPreFlightRequest(request)) {
            response.setStatus(HttpStatus.NO_CONTENT.value());
            return;
        }

        // if (!isValid) { // || CorsUtils.isPreFlightRequest(request)
        //
        // return;
        // }
        filterChain.doFilter(request, res);
    }

    private Logger logger = LoggerFactory.getLogger(getClass());

}
